/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package inamhi.gob.dp;

import gob.inamhi.md.ProcessedDataMD;
import gob.inamhi.md.RawDataMD;
import gob.inamhi.util.FechasUtiles;
import gob.inamhi.util.Operaciones;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.math3.util.Precision;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.InterruptableJob;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.UnableToInterruptJobException;

/**
 *
 * @author Diego
 */
@DisallowConcurrentExecution
public class HiloTarea implements InterruptableJob {

    private volatile Thread thisThread;

    public HiloTarea() {
    }

    @Override
    public void execute(JobExecutionContext jec) throws JobExecutionException {

        JobDataMap jdMap = jec.getJobDetail().getJobDataMap(); //Controla el estado de la tarea.
        String estado = jdMap.get("prpmesta").toString();      //Controla el estado de la tarea.
        if (estado.compareToIgnoreCase("t") == 0) {            //Relaciona el estado actual de la tarea, si es "t" se ejecuta, si es "f" no lo hace.
            Integer copaIn = Integer.parseInt(jdMap.get("copa__id").toString()); //Valor del parámetro a procesar.
            Integer copaOut = Integer.parseInt(jdMap.get("coparesu").toString()); //Valor del parámetro resultante.
            String pasoUnidad = jdMap.get("prpmpaso").toString();
            String operacion = jdMap.get("prpmoper").toString();               //Tipo de operación a aplicar a la lista de datos.
            String hora = jdMap.get("prpmhorc").toString();                    //Hora que se resta al inicio de la ejecución de la tarea desde donde se procesarán los datos.
            String tablaFuente = jdMap.get("prpmfnte").toString();
            Integer numeroDecimales = Integer.parseInt(jdMap.get("prpmdeci").toString());
            int estacion = Integer.parseInt(jdMap.get("esta__id").toString());
            int numeroDatosMin = Integer.parseInt(jdMap.get("prpmporc").toString());
            int id_configuracion = Integer.parseInt(jdMap.get("cfges__id").toString());
            String tablaDestino = jdMap.get("prpmdest").toString();
            System.out.println("Ejecutando... Estacion: " + estacion + " Parametro: " + copaOut);
            //            Date fechaEjecucion = jec.getScheduledFireTime();

            FechasUtiles fu = new FechasUtiles();                              //Objeto de tipo FechasUtiles para poder  obtener la fecha actual.
            String fechaActual = fu.getFechaYHoraActual();
            //            String fechaActual = fu.setFechaYHoraActual(fechaEjecucion);
            String fechaFin = fechaActual;                       //Fecha Actual de ejecución de la tarea
            String fechaInicio = fu.getFechaYHoraMenosUnaHoraAnterior(fechaActual, hora);   //Fecha Actual de ejecución de la tarea menos el tiempo de diferencia (prpmhorc)
            String fechaFinPaso = fu.getFechaYHoraMasUnaHoraPosterior(fechaInicio, pasoUnidad);
            String fechaInicioAux = fechaInicio;
            String fechaFinPasoAux = fechaFinPaso;
            RawDataMD est = new RawDataMD();                             //Clase para manejo de datos (Base de datos y consultas)
            ProcessedDataMD proc = new ProcessedDataMD();
            //            ArrayList<Integer> estaciones = est.getEstaciones(copaIn);           //Se obtienen las estaciones que midan el "copa" correspondiente
            //            Iterator it = estaciones.iterator();                               //iterador sobre la lista "estaciones".

            //            while (it.hasNext()) {                                             //Comienzo de iteración
            //                int estacion = (Integer) it.next();                            //Identificador de la estación, PK
            do {
                double[] datos = ArrayUtils.toPrimitive(est.getDatos(tablaFuente, copaIn, estacion, id_configuracion, fechaInicioAux, fechaFinPasoAux));     //Se obtiene la lista de datos desde la fecha de inicio hasta la fecha de fin de dicha estación 
                //con dicho copa(parámetro). Se utliza la libreria APACHE COMMONS UTIL para convertir la lista resultante en un arreglo. 
                int numeroDeDatos = datos.length;
                String id_dato = estacion + "_" + copaOut + "_" + id_configuracion + "_GPFT_" + fechaFinPasoAux.replaceAll(" ", "_");
                System.out.println("Numero de datos: " + numeroDeDatos);
                if (numeroDeDatos >= 1) {                                       //Si existen datos en el arreglo se ejecuta el siguiente bloque.
                    Operaciones op = new Operaciones();                        //Clase de utilidades para realizar operaciones aritméticas. 
                    Double resultado = op.operacion(datos, operacion);         //Se realiza la operación sobre los "datos" definida por la variable "operación".
                    resultado = Precision.round(resultado, numeroDecimales);                 //Se redondea el resultado a un decimal.
                    int nval = proc.buscarRepetido(tablaDestino, estacion, copaOut, id_configuracion, fechaFinPasoAux);
                    if (nval == -1) {
                        if (numeroDeDatos >= numeroDatosMin) {
                            System.out.println("Hora: " + fechaFinPasoAux + " estacion: " + estacion + " copa: " + copaOut + " Operación: " + operacion + ": " + resultado + " #Datos: " + numeroDeDatos);
                            proc.insertarDato(tablaDestino, id_dato, estacion, copaOut, 1, id_configuracion, fechaFinPasoAux, resultado, numeroDeDatos, true, "ADMIN");
                        } else {
                            System.out.println("Hora: " + fechaFinPasoAux + " estacion: " + estacion + " copa: " + copaOut + " Operación: " + operacion + ": " + resultado + " #Datos: " + numeroDeDatos);
                            proc.insertarDato(tablaDestino, id_dato, estacion, copaOut, 2, id_configuracion, fechaFinPasoAux, resultado, numeroDeDatos, true, "ADMIN");
                        }
                        //String tabla, int esta, int copa,int cali, String fecha, double valor, double nval,boolean estado,String uing

                    } else {
                        if (numeroDeDatos > nval) {
                            if (numeroDeDatos >= numeroDatosMin) {
                                System.out.println("Hora: " + fechaFinPasoAux + " estacion: " + estacion + " copa: " + copaOut + " Operación: " + operacion + ": " + resultado + " #Datos: " + numeroDeDatos);
                                proc.actualizarDato(tablaDestino, estacion, copaOut, 1, id_configuracion, fechaFinPasoAux, resultado, numeroDeDatos, "ADMIN", fechaActual);
                            }
                        }
                    }
                }
                fechaInicioAux = fechaFinPasoAux;
                fechaFinPasoAux = fu.getFechaYHoraMasUnaHoraPosterior(fechaInicioAux, pasoUnidad);
                //            } while (fechaFin.compareToIgnoreCase(fechaInicioAux) > 0);
            } while (fechaFin.compareToIgnoreCase(fechaFinPasoAux) > 0);
            //            fechaInicioAux = fechaInicio;
            //            fechaFinPasoAux = fechaFinPaso;
        }
    }

    @Override
    public void interrupt() throws UnableToInterruptJobException {
        thisThread = Thread.currentThread();
        if (thisThread != null) {
            // this call causes the ClosedByInterruptException to happen
            thisThread.interrupt();
        }
    }
}
//}
